/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package moviedownloader5;

import com.mycompany.moviedownloader.DbModel.Format;
import com.mycompany.moviedownloader.DbModel.Movie;
import com.mycompany.moviedownloader.DbModel.Person;
import comparator.Films;
import comparator.Matcher;
import comparator.Shows;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;

/**
 *
 * @author patrik
 */
public class MovieDownloader5 {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        
        final Films films = new Films();
        final Films films2 = new Films();
        final Films films3 = new Films();
        final Films films4 = new Films();
                
        Thread thread = new Thread(){

            @Override
            public void run() {
                Matcher matcher = new Matcher(films, 100000, 0);
                matcher.match();
            }
          
        };
        
        Thread thread2 = new Thread(){

            @Override
            public void run() {
                Matcher matcher = new Matcher(films2, 100000, 100000);
                matcher.match();
            }
          
        };
        
        Thread thread3 = new Thread(){

            @Override
            public void run() {
                Matcher matcher = new Matcher(films3, 100000, 200000);
                matcher.match();
            }
          
        };
        
        Thread thread4 = new Thread(){

            @Override
            public void run() {
                Matcher matcher = new Matcher(films4, 100000, 300000);
                matcher.match();
            }
          
        };
        
        thread.start();
        thread2.start();
        thread3.start();
        thread4.start();
        
        //doDaParsing();
        /*
         String shows = "D:\\PDT\\test\\";
         File file = new File(shows);
         Document doc = null;
         File[] files = file.listFiles();
         List<File> filess = new ArrayList<>(Arrays.asList(files));
         // MovieParser bager = new MovieParser(filess, new MovieToDatabase(DataSourceProvider.getDataSource()));
         bager.run();*/
    }

    private static class MovieParser implements Callable<List<Movie>> {

        private List<File> files;

        private static StringBuffer bugs = new StringBuffer(50000);

        public static void printBugs() {
            try {
                System.out.println("Oh Dude! some bugs has been there:");
                System.out.println(bugs);
                System.out.println("Or it was just fake?");
                File bugs = new File("d:\\PDT\\failed.txt");
                bugs.createNewFile();
                PrintWriter pw = new PrintWriter(bugs);
                pw.append(bugs.toString());
            } catch (IOException ex) {
                Logger.getLogger(MovieDownloader5.class.getName()).log(Level.SEVERE, "bugreport:" + bugs.toString(), ex);
            }
        }

        public MovieParser(List<File> files) {
            this.files = files;
        }

        @Override
        public List<Movie> call() throws Exception {
            List<Movie> movies = new ArrayList<>(files.size());
            Document doc = null;
            for (File file : files) {
                try {
                    doc = Jsoup.parse(file, null);
                    Movie movie = new Movie();
                    JPolievkaExtractor extractor = new JPolievkaExtractor(doc);
                    movie.setCsfdId(Movie.parseCsfdId(extractor.extractCSSFDAdress()));
                    movie.setCast(extractor.extractCast());
                    movie.setGenres(extractor.extractGenres());
                    movie.setNames(extractor.extractNames());
                    movie.setOrigin(extractor.extractOrigin());
                    movie.setRating(extractor.extractRating());
                    movie.setFormat(new Format(extractor.extractFormat()));
                    movie.setOriginalName(extractor.extractName());
                    movies.add(movie);
                } catch (IOException ex) {
                    //      System.out.println("bug:" + file.getName());
                    bugs.append(file.getName() + "\n");
                } catch (RuntimeException ex) {
                    //        System.out.println("bug:" + file.getName());
                    bugs.append(file.getName() + "\n");
                }

            }
            return movies;

        }

    }

    private static void doDaParsing() {
        Movie result = new Movie();
        String shows = "D:\\PDT\\movies";
        File file = new File(shows);
        Document doc = null;
        File[] files = file.listFiles();
        final int thredsCount = 8;
        final int batch = files.length / thredsCount;
        List<MovieParser> runnables = new ArrayList<>(thredsCount);
        for (int i = 0; i < thredsCount; i++) {
            List<File> tmp = new ArrayList<>(batch);
            for (int j = 0; j < batch; j++) {
                tmp.add(files[i * batch + j]);
            }
            runnables.add(new MovieParser(tmp));

        }

        ExecutorService executor = Executors.newFixedThreadPool(thredsCount);
        List<Future<List<Movie>>> results = new ArrayList<>();
        for (MovieParser movieParser : runnables) {
            results.add(executor.submit(movieParser));
        }
        List<Movie> movies = new ArrayList<>(files.length);
        for (Future<List<Movie>> future : results) {
            try {
                movies.addAll(future.get());
            } catch (InterruptedException ex) {
                Logger.getLogger(MovieDownloader5.class.getName()).log(Level.SEVERE, null, ex);
            } catch (ExecutionException ex) {
                Logger.getLogger(MovieDownloader5.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
        executor.shutdown();
        MovieParser.printBugs();
        Set<Person> people = new HashSet<>();
        for (Movie movie : movies) {
            people.addAll(movie.getCast());
        }
        try (MovieToDatabase mdb = new MovieToDatabase(DataSourceProvider.getDataSource())) {
            mdb.insertCast(people);
            for (Movie movie : movies) {
                try {
                    mdb.insert(movie);
                } catch (RuntimeException ex) {
                    Logger.getLogger(MovieDownloader5.class.getName()).log(Level.SEVERE, "saving movie failed", ex);
                }
                
            }
        }
        System.out.println("Job is done");
        System.exit(0);

    }

}
